package com.atguigu.gmall.order.mq;

import com.atguigu.gmall.common.config.mq.service.MqService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.msg.OrderCreateMsg;
import com.atguigu.gmall.order.service.OrderBizService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @Description
 * @Return
 * @Author https://weiranyi.github.io
 * @Date Created in 2022-12-23 10:31
 **/
@Slf4j
@Component
public class OrderCloseListener {
    @Autowired
    MqService mqService;
    @Autowired
    OrderBizService orderBizService;

    @RabbitListener(queues = MqConst.ORDER_DEAD_QUEUE)
    public void closeOrder(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 关单-------------------------------
            // 得到消息内容
            OrderCreateMsg orderCreateMsg = mqService.getMessageContent(message, OrderCreateMsg.class);
            /**
             * 查单关单必须为原子操作
             *  - 方案一：select * from order_info where user_id=? and id=? for update; 锁住记录，性能下降了
             *  - 方案二：利用CAS思想，乐观锁形式 比较并交换【本项目采用该方案】
             *      幂等性：n次请求的效果和一次是一样的
             */
            orderBizService.closeOrder(orderCreateMsg.getOrderId(), orderCreateMsg.getUserId());
            log.info("订单【{}】- 用户【{}】，关闭完成", orderCreateMsg.getOrderId(), orderCreateMsg.getUserId());
            channel.basicAck(deliveryTag, false); //回复ok
        } catch (Exception e) {
            log.error("关闭订单失败，原因是：{},正在重试...", e);
            mqService.retry(message, channel, MqConst.ORDER_RETRY_COUNT);
        }
    }
}
